﻿using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Publicuse.Util
{
    /// <summary>
    /// 爬虫工具类
    /// </summary>
    public class ReptilianUtil
    {
        private static ReptilianUtil reptilianUtil;

        private ReptilianUtil()
        {

        }

        static ReptilianUtil()
        {
            reptilianUtil = new ReptilianUtil();
        }

        public static ReptilianUtil GetReptilianUtil
        {
            get { return reptilianUtil; }
        }

        /// <summary>
        /// 下载html
        /// </summary>
        /// <param name="url"></param>
        /// <param name="cookie"></param>
        /// <param name="host"></param>
        /// <param name="type"></param>
        /// <param name="userAgent"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string DownloadHtml(string url, string cookie, string host, string type, string userAgent, string referer, out string msg)
        {
            string html = string.Empty;
            msg = string.Empty;
            try
            {
                HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
                request.Timeout = 30 * 1000;
                request.UserAgent = userAgent;
                request.ContentType = "text/html; charset=utf-8";
                request.Host = host;
                if (!string.IsNullOrEmpty(referer))
                    request.Referer = referer;

                request.Headers.Add("Cookie", @"" + cookie + "");
                request.Method = type;
                Encoding enc = Encoding.UTF8;
                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                    {
                    }
                    else
                    {
                        try
                        {
                            StreamReader sr = new StreamReader(response.GetResponseStream(), enc);
                            html = sr.ReadToEnd();
                            sr.Close();
                        }
                        catch (Exception ex)
                        {
                            html = null;
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                msg = ex.Message;
                if (ex.Message.Equals("远程服务器返回错误: (306)。"))
                {
                    html = null;
                }
            }
            catch (Exception ex)
            {
                msg = ex.Message;
                html = null;
            }
            return html;
        }

        /// <summary>
        ///  抓取正晚点网页信息
        /// </summary>
        /// <param name="html"></param>
        /// <param name="secondPathHtml"></param>
        /// <param name="action"></param>
        public void GetHtmlContextb(string html, string secondPathHtml, Action<QueryResult> func)
        {
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(html);
            string secondPath = secondPathHtml;
            HtmlNodeCollection nodeList = document.DocumentNode.SelectNodes(secondPath);
            if (nodeList != null)
            {
                var resultb = nodeList[0].InnerHtml;
                //var trlist = document.DocumentNode.SelectNodes("//*[@id='trainTable']/tr");
                var trlist = document.DocumentNode.SelectNodes("//*[@id='main']/div[3]/ul/li/table/tr");
                List<LatemessageExtend> extends = new List<LatemessageExtend>();
                QueryResult queryResult = new QueryResult()
                {
                    data = resultb,
                };
                if (trlist.Count > 1)
                {
                    queryResult.count = trlist.Count - 1;
                }
                func.Invoke(queryResult);
            }
        }

        /// <summary>
        ///  抓取正晚点网页信息
        /// </summary>
        /// <param name="html"></param>
        /// <param name="secondPathHtml"></param>
        /// <param name="action"></param>
        public void GetHtmlContext(string html, string secondPathHtml, Action<QueryResult> func)
        {
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(html);
            string secondPath = secondPathHtml;
            HtmlNodeCollection nodeList = document.DocumentNode.SelectNodes(secondPath);
            if (nodeList != null)
            {
                var resultb = nodeList[0].InnerHtml;
                //var trlist=document.DocumentNode.SelectNodes("//*[@id='trainTable']/tr");
                var trlist = document.DocumentNode.SelectNodes("//*[@id='main']/div[3]/ul/li/table/tr");
                List<LatemessageExtend> extends = new List<LatemessageExtend>();
                QueryResult queryResult = new QueryResult()
                {
                    data = resultb,
                };
                if (trlist != null)
                {
                    if (trlist.Count > 1)
                    {
                        queryResult.count = trlist.Count - 1;

                        int index = 0;
                        try
                        {
                            foreach (var item in trlist)
                            {
                                //if (index == 0)
                                //{
                                //    index++;
                                //    continue;
                                //}
                                LatemessageExtend latemessage = new LatemessageExtend();
                                var newindex = index + 1;
                                //latemessage.carNo = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[1]").FirstOrDefault().InnerText;
                                //latemessage.carStart = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[2]").FirstOrDefault().InnerText;
                                //latemessage.carEnd = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[3]").FirstOrDefault().InnerText;
                                //latemessage.carStartTime = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[4]").FirstOrDefault().InnerText;
                                //latemessage.carStation = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[5]").FirstOrDefault().InnerText;
                                //latemessage.carStatus = item.SelectNodes("//*[@id='trainTable']/tr[" + newindex + "]/td[6]").FirstOrDefault().InnerText;

                                latemessage.carNo = item.SelectNodes("//*[@class='train_num']")[index].InnerText;
                                latemessage.carStart = item.SelectNodes("//*[@class='shifa']")[index].InnerText;
                                latemessage.carEnd = item.SelectNodes("//*[@class='zhongdian']")[index].InnerText;
                                latemessage.carStartTime = item.SelectNodes("//*[@class='kaicheshijian']")[index].InnerText;
                                latemessage.carStation = item.SelectNodes("//*[@class='zhantai']")[index].InnerText;
                                if (item.InnerHtml.Contains("train_status"))
                                {
                                    var status = item.SelectNodes("//*[@class='train_status']");
                                    latemessage.carStatus = status.FirstOrDefault().InnerText;
                                }
                                else if (item.InnerHtml.Contains("checking"))
                                {
                                    var status = item.SelectNodes("//*[@class='checking']");
                                    latemessage.carStatus = status.FirstOrDefault().InnerText;
                                }
                                extends.Add(latemessage);
                                index++;
                            }
                        }
                        catch (Exception ex)
                        {
                            var exm = ex.Message;
                        }

                        queryResult.list = extends;
                    }
                    func.Invoke(queryResult);
                }

            }
        }

        /// <summary>
        /// 抓取重点城市天气情况网页信息
        /// </summary>
        /// <param name="url"></param>
        /// <param name="cityName"></param>
        /// <param name="wDirection"></param>
        /// <param name="func"></param>
        public void GetHtmlWeather(string url, string wDirection, string urlb, string urlc, string referer, Action<WeatherExtend> func)
        {
            string cookie = "vjuids=128bfab92.1667579eac6.0.5cd3686ef3cbc; vjlast=1539569216.1539569216.30; userNewsPort0=1; f_city=%E5%B9%BF%E5%B7%9E%7C101280101%7C; Wa_lvt_1=1539569217; Hm_lvt_080dabacb001ad3dc8b9b9049b36d43b=1539570090; UM_distinctid=16675873f7140e-0f0a59dc454a8f-5e442e19-144000-16675873f72a12; CNZZDATA1262608253=121807120-1539569252-null%7C1539569252; defaultCty=101280101; defaultCtyName=%u5E7F%u5DDE; Hm_lpvt_080dabacb001ad3dc8b9b9049b36d43b=1539587890; Wa_lpvt_1=1539587890";
            string host = "www.weather.com.cn";
            string type = "GET";
            string userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36";
            string msg = string.Empty;
            WeatherExtend weatherQuery = new WeatherExtend();
            host = "d1.weather.com.cn";
            var htmlb = this.DownloadHtml(urlb, cookie, host, type, userAgent, referer, out msg);
            HtmlDocument documentb = new HtmlDocument();
            documentb.LoadHtml(htmlb);
            string ta = string.Empty;
            string tb = string.Empty;
            if (documentb != null)
            {
                var datalist = "{" + documentb.Text.Split('{')[1];
                var da = JsonUtil.ToObject<DataSK>(datalist);
                if (da != null)
                {
                    weatherQuery.wRelativeHumidity = "相对湿度" + da.sd;//相对湿度
                    weatherQuery.wWindStatus = da.WD + da.WS;//风级状况
                }
            }

            var htmlc = this.DownloadHtml(urlc, cookie, host, type, userAgent, referer, out msg);
            HtmlDocument documentc = new HtmlDocument();
            documentc.LoadHtml(htmlc);
            if (documentc != null)
            {
                var datalist = documentc.Text.Split('=')[1].Split(';')[0];
                var da = JsonUtil.ToObject<Weatherinfodata>(datalist);
                if (da.weatherinfo != null)
                {
                    weatherQuery.wWeatherCondition = da.weatherinfo.weather; //天气状况
                    weatherQuery.wBTemperature = da.weatherinfo.temp;//白天温度
                    weatherQuery.wYTemperature = da.weatherinfo.tempn;//wYTemperature
                    weatherQuery.wName = da.weatherinfo.cityname;//城市名称
                }
            }
            weatherQuery.wcTime = DateTime.Now;
            weatherQuery.wDirection = wDirection;//城市方向
            func.Invoke(weatherQuery);
        }
    }

    public class LatemessageExtend
    {
        public string carNo { get; set; }

        public string carStart { get; set; }

        public string carEnd { get; set; }

        public string carStartTime { get; set; }

        public string carStation { get; set; }

        public string carStatus { get; set; }
    }

    public class QueryResult
    {
        public int count { get; set; }

        public string data { get; set; }

        public List<LatemessageExtend> list { get; set; }

        public QueryResult()
        {
            this.count = 0;
            this.data = string.Empty;
            this.list = new List<LatemessageExtend>();
        }
    }

    public class WeatherExtend
    {

        //[Name("城市名称")]
        public string wName { get; set; }

        //[Name("城市方向")]
        public string wDirection { get; set; }

        //[Name("相对湿度")]
        public string wRelativeHumidity { get; set; }

        //[Name("风级状况")]
        public string wWindStatus { get; set; }

        //[Name("白天温度")]
        public string wBTemperature { get; set; }

        //[Name("夜天温度")]
        public string wYTemperature { get; set; }

        //[Name("天气状况")]
        public string wWeatherCondition { get; set; }

        //[Name("日期")]
        public DateTime wcTime { get; set; }

        //[Name("更新日期")]
        public DateTime wuTime { get; set; }
    }

    public class WeatherType
    {
        public string url { get; set; }

        public string urlb { get; set; }
        public string urlc { get; set; }

        public string cityname { get; set; }

        public string directionname { get; set; }

        public string referer { get; set; }

    }
    public class DataSK
    {
        public string WD { get; set; }

        public string WS { get; set; }

        public string sd { get; set; }
    }

    public class Weatherinfodata
    {
        public Weatherinfo weatherinfo { get; set; }

    }

    public class Weatherinfo
    {
        public string temp { get; set; }

        public string tempn { get; set; }

        public string weather { get; set; }

        public string ws { get; set; }

        public string cityname { get; set; }

        public string city { get; set; }

        public string wd { get; set; }

    }
}
